<template>
  <div>
    <n-card title="人物信息" :header-style="{padding: '10px 10px 0px 10px'}" :content-style="{padding: '5px 5px 5px 5px'}">
      <template #header-extra>
        <n-space justify="end" style="margin-bottom: 5px">
          <n-button type="warning" size="small" @click="characterNameExtract">人物提取</n-button>
          <n-button type="primary" size="small" @click="resetFormData(); characterModal = true ">新增角色</n-button>
        </n-space>
      </template>
      <n-scrollbar
        trigger="none"
        :style="{ height: `${(clientHeight - (layoutHeaderHeight  + tabsHeight)+122)/2}px` }">
      <n-table striped>
        <thead>
        <tr>
          <th>操作</th>
          <th>名称</th>
          <th>别名</th>
          <th>头像</th>
          <th>性别</th>
          <th>lora</th>
          <th>描述</th>
        </tr>
        </thead>
        <tbody>

        <tr v-for="character in characterList">
          <td style="width: 50px">
            <n-space justify="center">
              <n-button
                block
                type="warning"
                 @click="deleteCharacter(character.id)">
                删除
              </n-button>
              <n-button block   type="primary"
                        @click="editCharacter(character)">编辑
              </n-button>
            </n-space>
          </td>
          <td style="width: 60px">{{ character.characterName }}</td>
          <td style="width: 60px">{{ character.characterNickname }}</td>
          <td style="width: 100px">
            <n-image
              v-if="character.characterAvatar"
              :width="100"
              :object-fit="'cover'"
             :src="fileFunction.getCharacterInfoImage(character.characterAvatar)"></n-image>
          </td>
          <td style="width: 80px">{{ character.characterGender}}</td>
          <td  >{{ character.characterLora }}</td>
          <td style="width: 200px;">
            <n-ellipsis  :line-clamp="4">
              {{ character.characterDescription }}
            </n-ellipsis>
          </td>
        </tr>

        </tbody>
      </n-table>
      </n-scrollbar>
    </n-card>
    <n-modal
      v-model:show="characterModal"
      class="custom-card"
      style="width: 600px"
      preset="card"
      title="新增人物信息"
      size="huge"
      :bordered="false"
    >
      <n-form
        ref="formRef"
        label-placement="left"
        :label-width="100"
        :style="{
            maxWidth: '640px'
          }"
        :rules="rules"
        :model="characterForm"
      >
        <n-form-item label="名称" path="characterName">
          <n-input v-model:value="characterForm.characterName" placeholder="人物名称"/>
        </n-form-item>
        <n-form-item label="性别" path="characterGender">
          <n-select :options="sexDict" v-model:value="characterForm.characterGender">
          </n-select>
        </n-form-item>
        <n-form-item label="别名" path="characterNickName">
          <n-dynamic-tags v-model:value="characterForm.characterNicknames" />
        </n-form-item>
        <n-form-item label="人物描述" path="characterDescription">
          <n-input v-model:value="characterForm.characterDescription" type="textarea" style="height: 100px;"
                   placeholder="人物性别,形象,衣着描述">
          </n-input>
          <n-button type="primary" style="height: 100px; margin-left: 5px;" @click="promptTemplateShow = true">
            提示词器
          </n-button>
        </n-form-item>

<!--        <n-form-item label="LoRA" path="characterLora">-->
<!--          <n-input v-model:value="characterForm.characterLora" placeholder="人物使用的LoRA">-->
<!--          </n-input>-->
<!--          <n-button type="primary" style="margin-left: 5px;" @click="modelSelectorShow = true">模型选择</n-button>-->
<!--        </n-form-item>-->

        <n-form-item label="MJ图片" path="engineType"  v-if=" characterForm.remoteUrl!= null &&  characterForm.remoteUrl.length>0">
          <n-tag type="primary" >
            <n-a target="_blank"
                 :href="characterForm.remoteUrl">
              人物图片
            </n-a>
          </n-tag>

          <n-tag type="primary" style="margin-left: 5px" v-if="characterForm.remoteStyleUrl!=null && characterForm.remoteStyleUrl.length > 0 " >
            <n-a target="_blank"
                 :href="characterForm.remoteStyleUrl">
              风格图片
            </n-a>
          </n-tag>
        </n-form-item>

        <n-form-item label=" " path="characterLora">
          <n-button type="primary" style="margin-left: 5px;" @click="characterInfoListShow = true">人物库选择</n-button>
        </n-form-item>
      </n-form>

      <n-space justify="end">
        <n-button type="primary" @click="addCharacter" :loading="addCharacterLoading">确定</n-button>
      </n-space>
    </n-modal>

    <n-drawer v-model:show="modelSelectorShow" :width="1200">
      <n-drawer-content title="Lora模型选择器" closable>
        <ModelSelector  modelType="lora" :storyId="props.storyId" @modelSelectEvent="modelSelectEvent"></ModelSelector>
      </n-drawer-content>
    </n-drawer>

    <n-drawer v-model:show="promptTemplateShow" :width="1200">
      <n-drawer-content title="提示词生成器" closable>
        <PromptTemplate code="03" @loadPromptEvent="loadPromptEvent"></PromptTemplate>
      </n-drawer-content>
    </n-drawer>


    <n-drawer v-model:show="characterInfoListShow" :width="1200">
      <n-drawer-content title="人物库选择" closable>
        <CharacterInfoList mode="choseCharacterInfo"  :choseCharacter="choseCharacter" ></CharacterInfoList>
      </n-drawer-content>
    </n-drawer>

  </div>

  <commonPromptChat :commonPromptSetting="commonPromptSetting" :closeAction="closeAction" v-model:show="commonPromptChatShow"></commonPromptChat>
</template>
<script setup lang="ts">
import {h, onMounted, reactive, ref} from "vue";
import {storyCharacterController} from "@/api/controller/story/storyCharacterController";
import {storyController} from "@/api/story/story.api";
import CharacterInfoList from "@/views/pages/configuration/character/index.vue";
import ModelSelector from '@/components/paint/modelSelector/modelSelector.vue'
import fileFunction from "@/libs/globalFunction/file";
import {NH5, NTag} from "naive-ui";
import PromptTemplate from "@/components/prompt/promptTemplate.vue";
import {storeToRefs} from "pinia";
import {useSystemStore} from "@/store/modules/useSystemStore";
import CommonPromptChat from "@/components/gpt/common/commonPromptChat.vue";


const characterList = ref(null)
const characterModal = ref(false)
const story = ref(null)
const promptTemplateShow = ref(false)
const modelSelectorShow = ref(false)
const addCharacterLoading = ref(false)
const characterInfoListShow = ref(false)
const formRef = ref(null)
const {
  clientHeight,
  layoutHeaderHeight,
  darkTheme,
  tabsHeight
} = storeToRefs(useSystemStore());
const commonPromptChatShow = ref(false)

import { JsonUtils } from '@/utils/jsonUtils'


const commonPromptSetting :Chat.CommonPromptSetting = {
  bizType: "custom_extract_character",
  bizData: [],
  resultRequire: "",
  saveResultFunction: (results:any) => {
    const isJSONArray = JsonUtils.isJsonArray(results[0].result)
    if (isJSONArray){
      const characterArray = JSON.parse(results[0].result)
      let characterMessage = h(NTag, {type: 'info',style: 'margin-left:2px'}, {default: () => '提取了 (' + characterArray.length +')个角色'})

      characterArray.forEach((item: any) => {
        characterMessage += " 人物名称: " + item.name + "  人物性别: "+ item.sex + " 人物描述: " + item.description
      })

      window.$dialog.info({
        title: "提醒",
        content: ()=>{
          let node = []
          node.push(h(NTag, {type: 'info',style: 'margin-left:2px'}, {default: () => '提取了 (' + characterArray.length +')个角色'}))
          characterArray.forEach((item: any) => {
            node.push(
                h(NTag, {type: 'info',style: 'margin-left:2px'},
                    {default: () => '人物名称 (' + item.name +')'}))
          })

          node.push(h(NH5,{showIcon:false},{default: () => '是否保存角色信息 ' }))
          return node;
        },
        positiveText: "确定",
        negativeText: "取消",
        onPositiveClick: () => {
          const characterArr = ref([])
          characterArray.forEach((item: any) => {
            const character = {
              characterName: item.name,
              characterDescription: item.description,
              characterGender: item.sex
            }
            characterArr.value.push(character)
          })
          storyCharacterController.addStoryCharacters(characterArr.value,story.value.id).then(res => {
            if (res.code === 200) {
              commonPromptChatShow.value = false
              window.$message.success(res.msg)
              getCharacterList()
            } else {
              window.$message.error(res.msg)
            }
          })
        }
      })
    }else {
      window.$message.error("返回的格式不对,可能为大模型推理错误,请重新推理，或者修改格式...")
    }
  },
  warningText: "推理文本过多会导致以下问题: \r 1) 大语言模型生成的时间过长，有可能会导致超时... \r 2) 超出模型的上下文限制，导致请求出错... \r 3) 建议文本字数控制在1000字以内...",
}

const sexDict = ref<Array<any>>([
  {
    label: "男性",
    value: "男性",
  },
  {
    label: "女性",
    value: "女性"
  }
])

const props = defineProps({
  storyId: {
    type: String,
    required: true
  },
  storyContent:{
    type:String,
    required: true
  }
})

const characterForm = ref(reactive({
  characterName: '',
  characterDescription: '',
  characterLora: '',
  chapterId: props.storyId,
  characterGender: '男性',
  characterAvatar: '',
  id: '',
  characterNicknames: [],
  characterNickname:'',
  styleAvatar: '',
  styleValue: 'default',
  remoteStyleUrl: '',
  ccRemoteUrl:''
}))


const rules = {
  characterName: [
    {required: true, message: '请输入人物名称', trigger: 'submit'}
  ],
  characterDescription: [
    {required: true, message: '请输入人物描述', trigger: 'submit'}
  ],
  characterGender: [
    {required: true, message: '请选择性别', trigger: 'submit'}
  ]
}


onMounted(() => {
  getCharacterList()
  getStory()
})

const getStory = async () => {
  storyController.getStoryById(props.storyId).then(res => {
    if (res.code === 200) {
      story.value = res.data.story
    } else {
      window.$message.error(res.msg)
    }
  })
}
const getCharacterList = () => {
  storyCharacterController.getCharacterList(props.storyId).then(res => {
    if (res.code === 200) {
      characterList.value = res.data
      characterList.value.forEach((item: any) => {
        console.log(item)
        if (item.characterNickname!=null && item.characterNickname.length>0){
          item.characterNicknames = item.characterNickname.split(',')
        }
      })
    }
  })
}

const deleteCharacter = (characterId: string) => {
  window.$dialog.error({
    title: "温馨提醒",
    content: "删除操作不可逆，是否继续？",
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: () => {
      storyCharacterController.deleteCharacter(characterId).then(res => {
        if (res.code === 200) {
          window.$message.success(res.msg)
          getCharacterList()
        }
      })
    }
  })
}


const editCharacter = (character: any) => {
  characterForm.value = {...character}
  characterModal.value = true
}


const resetFormData = () => {
  characterForm.value = {
    characterName: '',
    characterDescription: '',
    characterLora: '',
    chapterId: props.storyId,
    characterGender: '男性',
    characterAvatar: '',
    id: '',
    characterNicknames: [],
    characterNickname:'',
    remoteUrl:'',
    styleAvatar: '',
    styleValue: 'default',
    remoteStyleUrl: ''
  }
  characterForm.value.chapterId = props.storyId
}

const characterNameExtract =  () => {
  const bizData = ref([])
  const promptData = {
    'id': props.storyId,
    'index': 0 ,
    'content': props.storyContent,
    'result': ''
  }
  bizData.value.push(promptData)
  commonPromptSetting.bizData =  bizData.value
  commonPromptChatShow.value = true
}


const addCharacter = () => {

  formRef.value?.validate((errors) => {
    if (!errors) {
      addCharacterLoading.value = true
      if(characterForm.value.characterNicknames ){
        characterForm.value.characterNickname = characterForm.value.characterNicknames.join(',')
      }
      storyCharacterController.addCharacter(characterForm.value).then(res => {
        addCharacterLoading.value = false
        characterModal.value = false
        if (res.code === 200) {
          window.$message.success("操作成功!")
          getCharacterList()
        }
      }).finally(() => {
        addCharacterLoading.value = false
      })
    }
  })

}

const loadPromptEvent = (prompt: string, negativePrompt: string) => {
  characterForm.value.characterDescription = prompt
  promptTemplateShow.value = false
}


const modelSelectEvent = (modelObj: any) => {
  characterForm.value.characterLora = "<lora:" + modelObj.modelName + ":1>"
  modelSelectorShow.value = false
}


// 从人物库选取
const choseCharacter = (characterInfo: any) => {
    characterForm.value.characterLora = characterInfo.characterLora
    characterForm.value.characterDescription = characterInfo.characterDescription
    characterForm.value.characterGender = characterInfo.characterGender
    characterForm.value.characterAvatar = characterInfo.characterAvatar
    characterForm.value.characterNicknames = characterInfo.characterNicknames
    characterForm.value.characterNickname = characterInfo.characterNickname
    characterForm.value.ccRemoteUrl = characterInfo.ccRemoteUrl
    characterForm.value.styleAvatar = characterInfo.styleAvatar
    characterForm.value.styleValue = characterInfo.styleValue
    characterForm.value.remoteStyleUrl = characterInfo.remoteStyleUrl
    characterInfoListShow.value = false


}


const closeAction = () => {
  commonPromptChatShow.value = false
}
</script>
